2020_mohr_cube_limit_i_ii.py

#

SPDX-FileCopyrightText: 2020 Jeanne Mujawamariya & Sara Paolitto SPDX-FileCopyrightText: 2024 AlICe laboratory https://alicelab.be

SPDX-License-Identifier: GPL-3.0-or-later

import bpy
from random import randint
#

get object of given test is performed on lowered string

def _get_object(name):
#
    result = None
    for obj in bpy.data.objects:
        if obj.name.lower() == name.lower():
            result = obj
            break
    return result
#

returns the corners of the bounding box of an object in world coordinates

def get_BoundBox(object_name):
#
    from mathutils import Vector

    bpy.context.view_layer.update()
    ob = _get_object(object_name)
#

get list of vertices world coordinates

    bbox_corners = [ob.matrix_world @ Vector(corner) for corner in ob.bound_box]
    return bbox_corners
#

Check Collision of 2 Bounding Boxes box1 & box2 must be lists of Vectors, containg the edges of the bounding boxes

def check_Collision(box1, box2):
#
    print("[START]\tCOLLISION CHECK")
    x_max = max([e[0] for e in box1])
    x_min = min([e[0] for e in box1])
    y_max = max([e[1] for e in box1])
    y_min = min([e[1] for e in box1])
    z_max = max([e[2] for e in box1])
    z_min = min([e[2] for e in box1])
    print("[INFO] Box1 min %.2f, %.2f, %.2f" % (x_min, y_min, z_min))
    print("[INFO] Box1 max %.2f, %.2f, %.2f" % (x_max, y_max, z_max))
    x_max2 = max([e[0] for e in box2])
    x_min2 = min([e[0] for e in box2])
    y_max2 = max([e[1] for e in box2])
    y_min2 = min([e[1] for e in box2])
    z_max2 = max([e[2] for e in box2])
    z_min2 = min([e[2] for e in box2])
    print("[INFO] Box2 min %.2f, %.2f, %.2f" % (x_min2, y_min2, z_min2))
    print("[INFO] Box2 max %.2f, %.2f, %.2f" % (x_max2, y_max2, z_max2))
#

Check max and min values of coordinates Here, values must be inferior or equal

    isColliding = (
        (
            (x_max >= x_min2 and x_max <= x_max2)
            or (x_min <= x_max2 and x_min >= x_min2)
            or (x_max2 <= x_max and x_min2 >= x_min)
            or (x_max <= x_max2 and x_min >= x_min2)
        )
        and (
            (y_max >= y_min2 and y_max <= y_max2)
            or (y_min <= y_max2 and y_min >= y_min2)
            or (y_max2 <= y_max and y_min2 >= y_min)
            or (y_max <= y_max2 and y_min >= y_min2)
        )
        and (
            (z_max >= z_min2 and z_max <= z_max2)
            or (z_min <= z_max2 and z_min >= z_min2)
            or (z_max2 <= z_max and z_min2 >= z_min)
            or (z_max <= z_max2 and z_min >= z_min2)
        )
    )

    print("[END]\tCOLLISION CHECK")

    return isColliding
#
def make_cube(coord, vector):
    bpy.ops.mesh.primitive_cube_add(location=coord)
    bpy.ops.transform.resize(value=vector)
    cube = bpy.context.selected_objects[0]
    return cube
#
def structure(n):
#

initial cube

    x, y, z = (randint(0, 10), randint(0, 10), randint(0, 10))
    cube1 = make_cube((x, y, z), (0.5, 0.5, 0.5))
    cube_list = [cube1]
    while len(cube_list) < n:
#

adding a cube

        collision = False
        while not collision:
            x, y, z = (randint(0, 10), randint(0, 10), randint(0, 10))
            cube2 = make_cube((x, y, z), (1.5, 1.5, 1.5))
            for cube in cube_list:
                collision = check_Collision(
                    get_BoundBox(cube.name), get_BoundBox(cube2.name)
                )
            if not collision:
                bpy.ops.object.delete(use_global=False)
            else:
                cube_list.append(cube2)

    return cube_list
#
def join_objects(list):
    bpy.ops.object.select_all(action="DESELECT")
    for obj in list:
        obj.select_set(True)
    bpy.ops.object.join()
    new_structure = bpy.context.selected_objects[0]
    return new_structure
#
def rotation(object, rotation):
    bpy.ops.transform.rotate(value=rotation, orient_axis="Z")


structure1 = structure(10)
obj = join_objects(structure1)
obj.name = "inside smallcubes"
rotation(obj, -0.9)
structure2 = structure(3)
obj2 = join_objects(structure2)
obj2.name = "2 small cubes"
rotation(obj, -0.19)
#
def structure(n):
#

initial cube

    x, y, z = (randint(0, 5), randint(0, 5), randint(0, 5))
    cube1 = make_cube((x, y, z), (1.0, 1.0, 1.0))
    cube_list = [cube1]
    while len(cube_list) < n:
#

adding a cube

        collision = False
        while not collision:
            x, y, z = (randint(0, 10), randint(0, 10), randint(0, 10))
            cube2 = make_cube((x, y, z), (1, 1, 1))
            for cube in cube_list:
                collision = check_Collision(
                    get_BoundBox(cube.name), get_BoundBox(cube2.name)
                )
            if not collision:
                bpy.ops.object.delete(use_global=False)
            else:
                cube_list.append(cube2)

    return cube_list
#
def join_objects(list):
    bpy.ops.object.select_all(action="DESELECT")
    for obj in list:
        obj.select_set(True)
    bpy.ops.object.join()
    new_structure = bpy.context.selected_objects[0]
    return new_structure
#
def rotation(object, rotation):
    bpy.ops.transform.rotate(value=rotation, orient_axis="Y")


structure1 = structure(3)
obj = join_objects(structure1)
obj.name = "inside 2 smallcubes"
rotation(obj, -0.50)
structure2 = structure(2)
obj2 = join_objects(structure2)
obj2.name = "2 small cubes"
#

to create the outside big cube

def cube10():
    bpy.ops.mesh.primitive_cube_add(size=10, location=(5, 5, 5))


cube10()